package qq2564874169.tuaotuao.fx.orm.mybatis;

import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.EnumTypeHandler;
import org.apache.ibatis.type.JdbcType;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

public class EnumIdFieldTypeHandler extends BaseTypeHandler {
    private BaseTypeHandler typeHandler = null;
    private Map<Integer, Object> map = new HashMap<>();
    private Field field;

    public EnumIdFieldTypeHandler(Class type) {
        field = load(type);
        if (field == null) {
            typeHandler = new EnumTypeHandler(type);
        }
    }

    private Field load(Class type) {
        try {
            Field f = type.getDeclaredField("id");
            if (Modifier.isPublic(f.getModifiers()) && Modifier.isFinal(f.getModifiers()) && f.getType() == int.class) {
                f.trySetAccessible();
                Enum[] es = (Enum[]) type.getMethod("values").invoke(null);
                for (Enum item : es) {
                    Integer id = (Integer) f.get(item);
                    map.put(id, item);
                }
                return f;
            }
            return null;
        } catch (Exception e) {
            return null;
        }
    }

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, Object o, JdbcType jdbcType) throws SQLException {
        if (typeHandler != null) {
            typeHandler.setNonNullParameter(ps, i, o, jdbcType);
        } else {
            try {
                ps.setObject(i, field.get(o));
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public Object getNullableResult(ResultSet rs, String s) throws SQLException {
        if (typeHandler != null) {
            return typeHandler.getNullableResult(rs, s);
        } else {
            return map.get(rs.getInt(s));
        }
    }

    @Override
    public Object getNullableResult(ResultSet rs, int i) throws SQLException {
        if (typeHandler != null) {
            return typeHandler.getNullableResult(rs, i);
        } else {
            return map.get(rs.getInt(i));
        }
    }

    @Override
    public Object getNullableResult(CallableStatement cs, int i) throws SQLException {
        if (typeHandler != null) {
            return typeHandler.getNullableResult(cs, i);
        } else {
            return map.get(cs.getInt(i));
        }
    }
}
